

use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::collections::HashMap;
use std::string::String;

use std::io::{BufRead, BufReader, Read};



fn main() {

        let a = [ 4, 0, 1];

        let mut iter :Vec<_>= a.iter().map_while(|x| Some(2*x)).collect();
        println!("{:?}",iter);
        
        // Start a server listening on socket address
        
        let connection_listener = TcpListener::bind("127.0.01:8081").unwrap();
       
        // Listen to incoming connections in a loop
        for stream in connection_listener.incoming() {
            let mut stream = stream.unwrap();
            println!("Connection established");
            let mut read_buffer = [0; 128];
            //stream.read(&mut read_buffer).unwrap();
            // Convert HTTP request to Rust data structure
           // let req: String = String::from_utf8(read_buffer.to_vec()).unwrap();
           // println!("{}", req);
            // Route request to appropriate handler
           // Router::route(req, &mut stream);
           
           
           
            parse_req(&stream);
           
        }
 }  
 
 
 fn parse_req(mut stream: &TcpStream) -> (){
 
        let mut reader = BufReader::new(stream);
        // Read first line
        let mut http_request_line = String::new();
        let _result = reader.by_ref().read_line(&mut http_request_line);
        let http_request_line_split: Vec<&str> = http_request_line.split_whitespace().collect();

        // Input validation
        if http_request_line_split.len() != 3 {
            eprintln!("the first line has errors.");
        }

        // Process headers and body
        let mut http_request_headers = HashMap::new();
        for line_result in reader.by_ref().lines() {
            let line = match line_result {
                Ok(line_string) => line_string,
                Err(_error) => String::from("ERROR"),
            };
            if line == "" {
                break;
            }
            if line == "ERROR" {
                eprintln!("Failed to read line from TCP stream");
            }
            let mut iter = line.split(": ");
            let key = match iter.next() {
                Some(result) => result,
                None => "Error: no key",
            };
            if key == "Error: no key" {
                eprintln!("Failed to read line from TCP stream");
            }
            let value = match iter.next() {
                Some(result) => result,
                None => "Error: no value",
            };
            if value == "Error: no value" {
                eprintln!("Failed to read line from TCP stream");
            }
            http_request_headers.insert(key.to_lowercase(), String::from(value));
        }
        let mut body= Vec::new();
        // If content lenght header is set we assume it has a body and try to read it
        if http_request_headers.contains_key("content-length") {
            let body_length: i32 = match http_request_headers["content-length"].parse() {
                Ok(result) => result,
                Err(_error) => -1,
            };
            if body_length < 0 {
                eprintln!("Failed to read line from TCP stream");
            }
            let mut body_bytes = vec![0; body_length as usize];
            let result = reader.by_ref().read_exact(&mut body_bytes);
            let fail = match result {
                Ok(_result) => false,
                Err(_error) => true,
            };
            if fail {
                eprintln!("Failed to read line from TCP stream");
            } else {
                body = body_bytes;
            }
        } else {
            body = Vec::new();
        }
      
      println!("the body: {:?}", String::from_utf8(body.clone()).unwrap());
      stream.write(String::from_utf8(body).unwrap().as_bytes());
      stream.flush();
        
 }
